# -*- Mode: asm-mode -*-

/*
  S.M.A.C.K - An operating system kernel
  Copyright (C) 2010,2011 Mattias Holm and Kristian Rietveld
  For licensing and a full list of authors of the kernel, see the files
  COPYING and AUTHORS.
*/
	
/*
	This file contain the kernel bootstrap function, it is called by the
	bootloader, this code then does a couple of items:
	1. Clears the BSS section
	2. Initialise the SVC, ISR, FIQ, ABT and UND stacks.
	3. Initialise the MMU with a minimum set of pages.
	4. Calls the C-function boot

BUGS:	Does not inspect CPU to figure out whether we have an MMU or not. We
	should probably support MPUs as well.
*/

	# Mode symbols for use by cps instruction
	.equ USR_MODE, 0b10000
	.equ FIQ_MODE, 0b10001
	.equ IRQ_MODE, 0b10010
	.equ SVC_MODE, 0b10011
	.equ MON_MODE, 0b10110
	.equ ABT_MODE, 0b10111
	.equ UND_MODE, 0b11011
	.equ SYS_MODE, 0b11111

	.text
.global _start
_start:
	# Clear BSS section
	ldr r0, =_sbss
	ldr r1, =_ebss
	sub r1, r1, r0 			@ Compute BSS length
	lsl r1, #2			@ In words

	# Clear the BSS section
	cmp r1, #0			@ Skip if BSS is 0 long
	beq bsszero_end

	mov r2, #0			@ Load 0 for clearing
	mov r3, #0			@ Load 0 for index
bsszero:
	str r2, [r0, r3, LSL #2]	@ Store 0 to BSS section
	add r3, r3, #1			@ Increment loop counter
	cmp r1, r3
	bne bsszero			@ Done?
bsszero_end:	

	# SVC Stack
	ldr sp, =_svc_stack_bottom
	mov lr, #0			@ Clear the LR (for safety)
	# FIQ Stack
	cps #FIQ_MODE			@ Change to FIQ mode
	ldr sp, =_fiq_stack_bottom
	mov lr, #0			@ Clear the LR (for safety)
	# IRQ Stack
	cps #IRQ_MODE			@ Change to IRQ mode
	ldr sp, =_irq_stack_bottom
	mov lr, #0			@ Clear the LR (for safety)
	# ABT STACK
	cps #ABT_MODE			@ Change to ABT mode
	ldr sp, =_abt_stack_bottom
	mov lr, #0			@ Clear the LR (for safety)
	# UND Stack
	cps #UND_MODE			@ Change to UND mode
	ldr sp, =_und_stack_bottom
	mov lr, #0			@ Clear the LR (for safety)

	cps #SVC_MODE			@ Reenter SVC mode


	# At this point, all the priviliged stacks are setup, these all point
	# out physical addresses. Later on we will create a one to one mapping
	# for the kernels loaded sections and stacks. Even though we do not have
	# the MMU enabled at this point. Our stacks are ready and we simply call
	# the first C function here.

	ldr pc, =boot			@ Call boot C function, this will in term init the MMU

	.end
